home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_094 / clickupfront / clickupfront.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  9KB  |  290 lines

  1. /*
  2.  *  ClickUpFront.c  Brings a window to the front when you double-click
  3.  *                  in it (unless specified qualifier keys are also pressed).
  4.  *
  5.  *             Copyright (c) 1987 by Davide P. Cervone
  6.  *  You may use this code provided this copyright notice is left intact.
  7.  */
  8.  
  9. #include <exec/types.h>
  10. #include <libraries/dos.h>
  11. #include <exec/io.h>
  12. #include <exec/memory.h>
  13. #include <exec/interrupts.h>
  14. #include <devices/input.h>
  15. #include <devices/inputevent.h>
  16.  
  17. static char *program  = "ClickUpFront";
  18. static char *version  = "v1.0";
  19. static char *date     = "July 1987";
  20. static char *author   = "Copyright (c) 1987 by Davide P. Cervone";
  21.  
  22. static char *PortName = "ClickUpFrontPort";
  23. static char *handler  = "L:Click-Handler";     /* the handler file */
  24. #define HANDLER            &(handler[2])       /* without the "L:" */
  25.  
  26. #define STAYMASK      (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
  27.  
  28.  
  29. /*
  30.  *  This is the structure that holds the handler information between calls
  31.  *  to ClickUpFront.  We create a named, public message-port that points to
  32.  *  an instance of this structure so that we can find this information
  33.  *  when we are asked to remove the handler.  The PortName is stored here 
  34.  *  (NamedPort->mp_Node.ln_Name uses this area for it's name).   The other 
  35.  *  data are what we need in order to remove the handler and clean up properly.
  36.  */
  37.  
  38. struct HandlerBlock
  39. {
  40.    char *PortName;                  /* name of the public, named message-port */
  41.    struct Interrupt Handler;        /* the handler added to the handler chain */
  42.    struct IntuitionBase *Ibase;     /* library base used by the handler */
  43.    struct LayersBase *Lbase;        /* library base used by the handler */
  44.    long Segment;                    /* pointer from LoadSeg() */
  45. };
  46. #define HANDLERINFOSIZE     sizeof(struct HandlerBlock)
  47. #define NAMESIZE            (strlen(PortName)+1)
  48.  
  49. extern struct MsgPort *CreatePort();
  50. extern struct IOStdReq *CreateStdIO();
  51. extern struct MsgPort *FindPort(), *CreatePort();
  52. extern APTR AllocMem();
  53. extern long LoadSeg();
  54.  
  55. #define INTUITION_REV   0L
  56. #define LAYERS_REV      0L
  57.  
  58. struct IntuitionBase  *IntuitionBase = NULL;
  59. struct LayersBase     *LayersBase    = NULL;
  60. extern struct SysBase *SysBase;
  61.  
  62. struct MsgPort *InputPort = NULL;     /* Port used to talk to Input.Device */
  63. struct IOStdReq *InputBlock = NULL;   /* request block used with Input.Device */
  64. LONG InputDevice = 0;                 /* flag whether Input.Device is open */
  65. struct MsgPort *NamedPort = NULL;     /* holds info needed to remove handler */
  66. struct HandlerBlock *HandlerInfo = NULL; /* holds info stored in NamedPort */
  67.  
  68.  
  69. /*
  70.  *  DoExit()
  71.  *
  72.  *  General purpose exit routine.  If 's' is not NULL, then print an
  73.  *  error message with up to three parameters.  Free any memory, close
  74.  *  any open device, delete any ports, close any libraries, etc.
  75.  */
  76.  
  77. void DoExit(s,x1,x2,x3)
  78. char *s, *x1, *x2, *x3;
  79. {
  80.    long status = RETURN_OK;
  81.    
  82.    if (s != NULL)
  83.    {
  84.       printf(s,x1,x2,x3);
  85.       printf("\n");
  86.       status = RETURN_ERROR;
  87.    }
  88.    if (InputDevice)   CloseDevice(InputBlock);
  89.    if (InputBlock)    DeleteStdIO(InputBlock);
  90.    if (InputPort)     DeletePort(InputPort);
  91.    if (NamedPort)     DeletePort(NamedPort);
  92.    if (HandlerInfo)
  93.    {
  94.       if (HandlerInfo->PortName) FreeMem(HandlerInfo->PortName,NAMESIZE);
  95.       FreeMem(HandlerInfo,HANDLERINFOSIZE);
  96.    }
  97.    if (IntuitionBase) CloseLibrary(IntuitionBase);
  98.    if (LayersBase)    CloseLibrary(LayersBase);
  99.    exit(status);
  100. }
  101.  
  102.  
  103. /*
  104.  *  CheckLibOpen()
  105.  *
  106.  *  General library open routine.  It opens a library and sets a pointer
  107.  *  to it.  It checks that the library was openned successfully.
  108.  */
  109.  
  110. void CheckLibOpen(lib,name,rev)
  111. APTR *lib;
  112. char *name;
  113. int rev;
  114. {
  115.    extern APTR OpenLibrary();
  116.  
  117.    if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
  118.       DoExit("Can't open '%s'\n",name);
  119. }
  120.  
  121.  
  122. /*
  123.  *  Macros that make memory allocation easier.
  124.  */
  125. #define NEW(s,var)      (var = (struct s *)New("var",sizeof(struct s)))
  126. #define NEWCHAR(var,s)  (var = (char *)New("var",s))
  127.  
  128.  
  129. /*
  130.  *  New()
  131.  *
  132.  *  Allocate public memory of a given size and set it to all zeros.  If there
  133.  *  is not enough memory, then exit with an error, otherwise return the
  134.  *  pointer to the newly allocated memory.
  135.  */
  136.  
  137. APTR New(name,size)
  138. char *name;
  139. int size;
  140. {
  141.    APTR ptr;
  142.    
  143.    if ((ptr = AllocMem(size,MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  144.       DoExit("Can't Get Memory for '%s'");
  145.    return(ptr);
  146. }
  147.  
  148.  
  149. /*
  150.  *  TellInputDevice()
  151.  *
  152.  *  Create a port and I/O block, and open the input device.  Set up the
  153.  *  I/O block to add or remove the input handler, and send the request
  154.  *  to the input device.  Finally, close the device and delete the
  155.  *  I/O block and port.
  156.  */
  157.  
  158. void TellInputDevice(function)
  159. int function;
  160. {
  161.    long status;
  162.  
  163.    if ((InputPort = CreatePort(0,0)) == NULL) DoExit("Can't Create Port");
  164.    if ((InputBlock = CreateStdIO(InputPort)) == NULL)
  165.       DoExit("Can't Create Standard IO Block");
  166.    InputDevice = (OpenDevice("input.device",0,InputBlock,0) == 0);
  167.    if (InputDevice == FALSE) DoExit("Can't Open 'input.device'");
  168.    
  169.    InputBlock->io_Command = (long) function;
  170.    InputBlock->io_Data    = (APTR) &(HandlerInfo->Handler);
  171.    if (status = DoIO(InputBlock)) DoExit("Error from DoIO:  %ld",status);
  172.  
  173.    CloseDevice(InputBlock);
  174.    DeleteStdIO(InputBlock);
  175.    DeletePort(InputPort);
  176. }
  177.  
  178.  
  179. /*
  180.  *  CreateHandler()
  181.  *
  182.  *  Open the libraries needed by the input handler and store their locations
  183.  *  in the HandlerInfo structure (so we can close them later).  Try to 
  184.  *  LoadSeg() the handler.  If it is not in the current directory, try the
  185.  *  L: directory.  Exit with an error if the handler can't be found.
  186.  *  Convert the segment pointer into a pointer to the Setup routine (the
  187.  *  first routine in the handler executable).  Call Setup() and pass it
  188.  *  the pointers to the libraries that it will need to use.  Setup() returns
  189.  *  a pointer to the actual handler routine that should be added into the
  190.  *  input handler chain.  Store this in the HandlerInfo structure so we
  191.  *  can use it to remove the handler later.  Set the handler priority to
  192.  *  51 so that it is ahead of Intuition.
  193.  *
  194.  *  Finally, add the handler in the chain and tell the user that the
  195.  *  handler has been installed.
  196.  */
  197.  
  198. void CreateHandler(argc,argv)
  199. int argc;
  200. char **argv;
  201. {
  202.    long (*Setup)();
  203.    long flags = STAYMASK;
  204.  
  205.    CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
  206.    CheckLibOpen(&LayersBase,"layers.library",LAYERS_REV);
  207.    
  208.    if (argc > 1) sscanf(argv[1],"%lx",&flags);
  209.  
  210.    HandlerInfo->Ibase = IntuitionBase;
  211.    HandlerInfo->Lbase = LayersBase;
  212.    if ((HandlerInfo->Segment = LoadSeg(HANDLER)) == NULL)
  213.       if ((HandlerInfo->Segment = LoadSeg(handler)) == NULL)
  214.          DoExit("Can't Load '%s'",handler);
  215.    Setup = (long (*)()) ((HandlerInfo->Segment << 2) + 4);
  216.    HandlerInfo->Handler.is_Code = 
  217.       (void (*)()) ((*Setup)(IntuitionBase,LayersBase,SysBase,flags));
  218.    HandlerInfo->Handler.is_Node.ln_Pri = 51;
  219.  
  220.    TellInputDevice(IND_ADDHANDLER);
  221.    printf("%s %s (%s) Installed\n",program,version,date);
  222. }
  223.  
  224.  
  225. /*
  226.  *  Delete Handler()
  227.  *
  228.  *  Retreive the library pointers fro mthe HandlerInfo structure, where
  229.  *  we stored them when we originally installed the handler, then remove
  230.  *  the handler from the input handler chain.  Tell the user that the
  231.  *  handler is gone, and then close the libraries that are no longer needed.
  232.  */
  233.  
  234. void DeleteHandler()
  235. {
  236.    IntuitionBase = HandlerInfo->Ibase;
  237.    LayersBase    = HandlerInfo->Lbase;
  238.  
  239.    TellInputDevice(IND_REMHANDLER);
  240.    UnLoadSeg(HandlerInfo->Segment);
  241.    printf("%s Removed\n",program);
  242.    
  243.    CloseLibrary(IntuitionBase);
  244.    CloseLibrary(LayersBase);
  245. }
  246.  
  247.  
  248. /*
  249.  *  main()
  250.  *
  251.  *  Check if a message port with our name already exists.
  252.  *  If not, then the handler is not already installed, so:
  253.  *    Allocate a new HandlerInfo structure and initialize the port name.
  254.  *    Create a public, named message-port (we will look for this the next
  255.  *      time ClickUpFront is called).
  256.  *    Make the message port point to the HandlerInfo structure so we
  257.  *      can use it later when the user asks us to remove the handler.
  258.  *      Note that the port is not actually used for putting and getting
  259.  *      messages, so the Task field is never used, so we can take it for
  260.  *      our own uses.
  261.  *    Finally, add the input handler into the chain.
  262.  *  Otherwise, the port exists, so ClickUpFront already is installed:
  263.  *    Retreive the HandlerInfo poiner from the port, and remove the 
  264.  *      handler from the input handler chain.
  265.  *    Free the memory used by the HandlerInfo, and delete the message port.
  266.  */
  267.  
  268. void main(argc,argv)
  269. int argc;
  270. char **argv;
  271. {
  272.    NamedPort = FindPort(PortName);
  273.    if (NamedPort == NULL)
  274.    {
  275.       NEW(HandlerBlock,HandlerInfo);
  276.       NEWCHAR(HandlerInfo->PortName,NAMESIZE);
  277.       strcpy(HandlerInfo->PortName,PortName);
  278.       if ((NamedPort = CreatePort(HandlerInfo->PortName,0)) == NULL)
  279.          DoExit("Can't Create Message Port '%s'",PortName);
  280.       NamedPort->mp_SigTask = (struct Task *)HandlerInfo;
  281.       CreateHandler(argc,argv);
  282.    } else {
  283.       HandlerInfo = (struct HandlerBlock *)(NamedPort->mp_SigTask);
  284.       DeleteHandler();
  285.       FreeMem(HandlerInfo->PortName,NAMESIZE);
  286.       FreeMem(HandlerInfo,HANDLERINFOSIZE);
  287.       DeletePort(NamedPort);
  288.    }
  289. }
  290.